using Avalonia;
using Avalonia.Controls;
using Avalonia.Layout;
using System;
using System.Collections.Generic;
using System.Linq;

namespace AvaloniaUiKit.Controls
{
    public class FlexWrapPanel : Panel
    {
        #region 依赖属性定义

        public static readonly StyledProperty<Orientation> OrientationProperty =
            AvaloniaProperty.Register<FlexWrapPanel, Orientation>(nameof(Orientation), Orientation.Horizontal);

        public static readonly StyledProperty<double> ItemSpacingProperty =
            AvaloniaProperty.Register<FlexWrapPanel, double>(nameof(ItemSpacing), 0);

        public static readonly StyledProperty<double> HorizontalSpacingProperty = 
            AvaloniaProperty.Register<FlexWrapPanel, double>(nameof(HorizontalSpacing), 0);

        public static readonly StyledProperty<double> VerticalSpacingProperty = 
            AvaloniaProperty.Register<FlexWrapPanel, double>(nameof(VerticalSpacing), 0);

        #endregion

        #region 属性

        /// <summary>
        /// 获取或设置布局方向
        /// </summary>
        public Orientation Orientation
        {
            get => GetValue(OrientationProperty);
            set => SetValue(OrientationProperty, value);
        }

        /// <summary>
        /// 获取或设置项之间的统一间距（同时设置水平和垂直间距）
        /// </summary>
        public double ItemSpacing
        {
            get => GetValue(ItemSpacingProperty);
            set => SetValue(ItemSpacingProperty, value);
        }

        /// <summary>
        /// 获取或设置项之间的水平间距
        /// </summary>
        public double HorizontalSpacing
        {
            get => GetValue(HorizontalSpacingProperty);
            set => SetValue(HorizontalSpacingProperty, value);
        }

        /// <summary>
        /// 获取或设置项之间的垂直间距
        /// </summary>
        public double VerticalSpacing
        {
            get => GetValue(VerticalSpacingProperty);
            set => SetValue(VerticalSpacingProperty, value);
        }

        #endregion

        public FlexWrapPanel()
        {
            // 监听属性变化，触发重新布局
            AffectsMeasure<FlexWrapPanel>(OrientationProperty);
            AffectsMeasure<FlexWrapPanel>(ItemSpacingProperty);
            AffectsMeasure<FlexWrapPanel>(HorizontalSpacingProperty);
            AffectsMeasure<FlexWrapPanel>(VerticalSpacingProperty);
        }

        #region 布局实现

        protected override Size MeasureOverride(Size availableSize)
        {
            double hSpacing = HorizontalSpacing > 0 ? HorizontalSpacing : ItemSpacing;
            double vSpacing = VerticalSpacing > 0 ? VerticalSpacing : ItemSpacing;
            
            // 获取所有可见的子元素
            var children = Children.Where(child => child.IsVisible);

            // 初始化面板所需尺寸
            Size panelSize = new Size();
            
            if (Orientation == Orientation.Horizontal)
            {
                // 水平方向布局 - 分行排列
                double lineHeight = 0;
                double accumulatedWidth = 0;
                double maxWidth = double.IsPositiveInfinity(availableSize.Width) ? 
                    double.PositiveInfinity : availableSize.Width;
                double totalHeight = 0;

                foreach (var child in children)
                {
                    // 测量子元素
                    child.Measure(availableSize);
                    var childSize = child.DesiredSize;
                    
                    // 检查是否需要换行
                    if (accumulatedWidth + childSize.Width > maxWidth && accumulatedWidth > 0)
                    {
                        // 换行
                        panelSize = panelSize.WithWidth(Math.Max(panelSize.Width, accumulatedWidth));
                        totalHeight += lineHeight + vSpacing;
                        accumulatedWidth = childSize.Width;
                        lineHeight = childSize.Height;
                    }
                    else
                    {
                        // 继续当前行
                        accumulatedWidth += (accumulatedWidth > 0 ? hSpacing : 0) + childSize.Width;
                        lineHeight = Math.Max(lineHeight, childSize.Height);
                    }
                }

                // 处理最后一行
                panelSize = panelSize.WithWidth(Math.Max(panelSize.Width, accumulatedWidth));
                totalHeight += lineHeight;
                
                // 设置最终高度
                panelSize = panelSize.WithHeight(totalHeight);
            }
            else
            {
                // 垂直方向布局 - 分列排列
                double columnWidth = 0;
                double accumulatedHeight = 0;
                double maxHeight = double.IsPositiveInfinity(availableSize.Height) ? 
                    double.PositiveInfinity : availableSize.Height;
                double totalWidth = 0;

                foreach (var child in children)
                {
                    // 测量子元素
                    child.Measure(availableSize);
                    var childSize = child.DesiredSize;
                    
                    // 检查是否需要换列
                    if (accumulatedHeight + childSize.Height > maxHeight && accumulatedHeight > 0)
                    {
                        // 换列
                        panelSize = panelSize.WithHeight(Math.Max(panelSize.Height, accumulatedHeight));
                        totalWidth += columnWidth + hSpacing;
                        accumulatedHeight = childSize.Height;
                        columnWidth = childSize.Width;
                    }
                    else
                    {
                        // 继续当前列
                        accumulatedHeight += (accumulatedHeight > 0 ? vSpacing : 0) + childSize.Height;
                        columnWidth = Math.Max(columnWidth, childSize.Width);
                    }
                }

                // 处理最后一列
                panelSize = panelSize.WithHeight(Math.Max(panelSize.Height, accumulatedHeight));
                totalWidth += columnWidth;
                
                // 设置最终宽度
                panelSize = panelSize.WithWidth(totalWidth);
            }

            return panelSize;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            double hSpacing = HorizontalSpacing > 0 ? HorizontalSpacing : ItemSpacing;
            double vSpacing = VerticalSpacing > 0 ? VerticalSpacing : ItemSpacing;
            
            var children = Children.Where(child => child.IsVisible).ToList();
            
            if (children.Count == 0)
            {
                return finalSize;
            }

            if (Orientation == Orientation.Horizontal)
            {
                // 水平方向布局
                double x = 0;
                double y = 0;
                double lineHeight = 0;

                foreach (var child in children)
                {
                    var childSize = child.DesiredSize;
                    
                    // 检查是否需要换行
                    if (x + childSize.Width > finalSize.Width && x > 0)
                    {
                        // 换行
                        x = 0;
                        y += lineHeight + vSpacing;
                        lineHeight = 0;
                    }

                    // 安排子元素位置
                    child.Arrange(new Rect(x, y, childSize.Width, childSize.Height));
                    
                    // 更新位置和行高
                    x += childSize.Width + hSpacing;
                    lineHeight = Math.Max(lineHeight, childSize.Height);
                }
            }
            else
            {
                // 垂直方向布局
                double x = 0;
                double y = 0;
                double columnWidth = 0;

                foreach (var child in children)
                {
                    var childSize = child.DesiredSize;
                    
                    // 检查是否需要换列
                    if (y + childSize.Height > finalSize.Height && y > 0)
                    {
                        // 换列
                        y = 0;
                        x += columnWidth + hSpacing;
                        columnWidth = 0;
                    }

                    // 安排子元素位置
                    child.Arrange(new Rect(x, y, childSize.Width, childSize.Height));
                    
                    // 更新位置和列宽
                    y += childSize.Height + vSpacing;
                    columnWidth = Math.Max(columnWidth, childSize.Width);
                }
            }

            return finalSize;
        }

        #endregion
    }
}